﻿namespace OasisCiq.Xml
{
    // ReSharper disable MemberCanBePrivate.Global

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Xml;
    using CommonTypes;
    using Xnl;
    using Xpil;
    using XS;

    public class XpilXmlReader
    {
        private const string XmlNS = XmlNamespaces.Party;
        private readonly XmlReader reader;
        private readonly CommonTypesXmlReader ctReader = new CommonTypesXmlReader();
        private readonly XnlXmlReader xnlReader;
        private readonly XalXmlReader xalReader;
        private readonly XLinkXmlReader xLinkReader = new XLinkXmlReader();

        public XpilXmlReader(XmlReader reader)
        {
            this.reader = reader;
            xnlReader = new XnlXmlReader(reader);
            xalReader = new XalXmlReader(reader);
        }

        public Accounts ReadAccounts()
        {
            if (!CheckElement("Accounts"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Accounts();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Account
            while (CheckElement("Account"))
            {
                var account = ReadAccount();
                element.Add(account);
            }

            reader.Read(); // from a:Account empty or end element to next node
            return element;
        }

        public Account ReadAccount()
        {
            if (!CheckElement("Account"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Account();
            attrs = ReadAccountAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to p:AccountElement or p:Organisation
            }

            while (CheckElement("AccountElement"))
            {
                var accountElement = ReadAccountElement();
                if (element.AccountElements == null)
                {
                    element.AccountElements = new List<AccountElement>();
                }

                element.AccountElements.Add(accountElement);
            }

            element.Organization = xnlReader.ReadOrganisationName("Organisation", XmlNS);
            reader.Read(); // from a:Account empty or end element to next node
            return element;
        }

        public AccountElement ReadAccountElement()
        {
            if (!CheckElement("AccountElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new AccountElement(value);
            attrs = ReadAccountElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Addresses ReadAddresses()
        {
            if (!CheckElement("Addresses"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Addresses();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Address
            while (CheckElement("Address"))
            {
                var address = xalReader.ReadAddress("Address", XmlNS);
                element.Add(address);
            }

            reader.Read(); // from a:Addresses end element to next node
            return element;
        }

        public BirthInfoElement ReadBirthInfoElement()
        {
            if (!CheckElement("BirthInfoElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new BirthInfoElement(value);
            attrs = ReadBirthInfoElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public BirthInfo ReadBirthInfo()
        {
            if (!CheckElement("BirthInfo"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new BirthInfo();
            attrs = ReadBirthInfoAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first p:BirthInfoElement or p:BirthPlaceDetails
                while (true)
                {
                    var infoElement = ReadBirthInfoElement();
                    if (infoElement == null)
                    {
                        break;
                    }

                    element.Add(infoElement);
                }

                element.BirthPlaceDetails = xalReader.ReadAddress("BirthPlaceDetails", XmlNS);
            }

            reader.Read(); // from p:BirthInfo empty or end element to next node
            return element;
        }

        public ContactNumberElement ReadContactNumberElement()
        {
            if (!CheckElement("ContactNumberElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new ContactNumberElement(value);
            attrs = ReadContactNumberElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public ContactNumber ReadContactNumber()
        {
            if (!CheckElement("ContactNumber"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new ContactNumber();
            attrs = ReadContactNumberAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first p:ContactNumberElement
                while (true)
                {
                    var contactNumberElement = ReadContactNumberElement();
                    if (contactNumberElement == null)
                    {
                        break;
                    }

                    element.Add(contactNumberElement);
                }
            }

            reader.Read(); // from p:ContactNumber empty or end element to next node
            return element;
        }

        public ContactNumbers ReadContactNumbers()
        {
            if (!CheckElement("ContactNumbers"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new ContactNumbers();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:ContactNumber
            while (true)
            {
                var contactNumber = ReadContactNumber();
                if (contactNumber == null)
                {
                    break;
                }

                element.Add(contactNumber);
            }

            reader.Read(); // from p:ContactNumbers end element to next node
            return element;
        }

        public CountryOfResidence ReadCountryOfResidence()
        {
            if (!CheckElement("Country"))
            {
                return null;
            }

            var element = (CountryOfResidence)xalReader.ReadCountry(new CountryOfResidence(), "Country", XmlNS);
            var attrs = _XmlAttribute.GetAttributes(element.ExtendedAttributes);
            attrs = ReadCountryOfResidenceAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            element.ExtendedAttributes = _XmlAttribute.RemoveMissedAttributes(element.ExtendedAttributes, attrs);
            return element;
        }

        public CountriesOfResidence ReadCountriesOfResidence()
        {
            if (!CheckElement("CountriesOfResidence"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new CountriesOfResidence();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Country
            while (true)
            {
                var country = ReadCountryOfResidence();
                if (country == null)
                {
                    break;
                }

                element.Add(country);
            }

            reader.Read(); // from p:CountriesOfResidence end element to next node
            return element;
        }

        public DocumentElement ReadDocumentElement()
        {
            if (!CheckElement("DocumentElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new DocumentElement(value);
            attrs = ReadDocumentElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Document ReadDocument()
        {
            if (!CheckElement("Document"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Document();
            attrs = ReadDocumentAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child node
                while (true)
                {
                    var documentElement = ReadDocumentElement();
                    if (documentElement == null)
                    {
                        break;
                    }

                    element.Add(documentElement);
                }

                element.NameOnDocument = xnlReader.ReadPartyName("NameOnDocument", XmlNS);
                element.AddressOnDocument = xalReader.ReadAddress("AddressOnDocument", XmlNS);
                element.IssuerName = xnlReader.ReadOrganisationName("IssuerName", XmlNS);
            }

            reader.Read(); // from empty or end p:Document to next node
            return element;
        }

        public Documents ReadDocuments()
        {
            if (!CheckElement("Documents"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Documents();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Document node
            while (true)
            {
                var document = ReadDocument();
                if (document == null)
                {
                    break;
                }

                element.Add(document);
            }

            reader.Read(); // from p:Documents end element to next node
            return element;
        }

        public ElectronicAddressIdentifier ReadElectronicAddressIdentifier()
        {
            if (!CheckElement("ElectronicAddressIdentifier"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new ElectronicAddressIdentifier(value);
            attrs = ReadElectronicAddressIdentifierAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public ElectronicAddressIdentifiers ReadElectronicAddressIdentifiers()
        {
            if (!CheckElement("ElectronicAddressIdentifiers"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new ElectronicAddressIdentifiers();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child node
            while (true)
            {
                var electronicAddressIdentifier = ReadElectronicAddressIdentifier();
                if (electronicAddressIdentifier == null)
                {
                    break;
                }

                element.Add(electronicAddressIdentifier);
            }

            reader.Read(); // from end of p:ElectronicAddressIdentifiers to next node
            return element;
        }

        public Event ReadEvent()
        {
            if (!CheckElement("Event"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Event(value);
            attrs = ReadEventAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Events ReadEvents()
        {
            if (!CheckElement("Events"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Events();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Event
            while (true)
            {
                var @event = ReadEvent();
                if (@event == null)
                {
                    break;
                }

                element.Add(@event);
            }

            reader.Read(); // from p:Events end element to next node
            return element;
        }

        public Favourite ReadFavourite()
        {
            if (!CheckElement("Favourite"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Favourite(value);
            attrs = ReadFavouriteAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Favourites ReadFavourites()
        {
            if (!CheckElement("Favourites"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Favourites();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Favourite element
            var favourite = ReadFavourite();
            while (favourite != null)
            {
                element.Add(favourite);
                favourite = ReadFavourite();
            }

            reader.Read(); // from p:Favourites end element to next node
            return element;
        }

        public FreeTextLine ReadFreeTextLine()
        {
            if (!CheckElement("FreeTextLine"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new FreeTextLine(value);
            attrs = ReadFreeTextLineAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public FreeTextLines ReadFreeTextLines()
        {
            if (!CheckElement("FreeTextLines"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new FreeTextLines();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:FreeTextLine element
            var textLine = ReadFreeTextLine();
            while (textLine != null)
            {
                element.Add(textLine);
                textLine = ReadFreeTextLine();
            }

            reader.Read(); // from p:FreeTextLines end element to next node
            return element;
        }

        public Habit ReadHabit()
        {
            if (!CheckElement("Habit"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Habit(value);
            attrs = ReadHabitAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Habits ReadHabits()
        {
            if (!CheckElement("Habits"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Habits();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Habit element
            var habit = ReadHabit();
            while (habit != null)
            {
                element.Add(habit);
                habit = ReadHabit();
            }

            reader.Read(); // from p:Habits end element to next node
            return element;
        }

        public Hobby ReadHobby()
        {
            if (!CheckElement("Hobby"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Hobby(value);
            attrs = ReadHobbyAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Hobbies ReadHobbies()
        {
            if (!CheckElement("Hobbies"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Hobbies();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first p:Hobby element
            var sub1 = ReadHobby();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadHobby();
            }

            reader.Read(); // from p:Hobbies end element to next node
            return element;
        }

        public IdentifierElement ReadIdentifierElement()
        {
            if (!CheckElement("IdentifierElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new IdentifierElement(value);
            attrs = ReadIdentifierElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Identifier ReadIdentifier()
        {
            if (!CheckElement("Identifier"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Identifier();
            attrs = ReadIdentifierAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                var sub1 = ReadIdentifierElement();
                while (sub1 != null)
                {
                    element.Add(sub1);
                    sub1 = ReadIdentifierElement();
                }

                element.IssuerName = xnlReader.ReadOrganisationName("IssuerName", XmlNS);
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public Identifiers ReadIdentifiers()
        {
            if (!CheckElement("Identifiers"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Identifiers();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadIdentifier();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadIdentifier();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public Language ReadLanguage()
        {
            if (!CheckElement("Language"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Language(value);
            attrs = ReadLanguageAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Languages ReadLanguages()
        {
            if (!CheckElement("Languages"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Languages();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadLanguage();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadLanguage();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public MembershipElement ReadMembershipElement()
        {
            if (!CheckElement("MembershipElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new MembershipElement(value);
            attrs = ReadMembershipElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Membership ReadMembership()
        {
            if (!CheckElement("Membership"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Membership();
            attrs = ReadMembershipAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                var sub1 = ReadMembershipElement();
                while (sub1 != null)
                {
                    element.Add(sub1);
                    sub1 = ReadMembershipElement();
                }

                element.Organisation = xnlReader.ReadOrganisationName("Organisation", XmlNS);
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public Memberships ReadMemberships()
        {
            if (!CheckElement("Memberships"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Memberships();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadMembership();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadMembership();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public NationalityCountry ReadNationalityCountry()
        {
            if (!CheckElement("Country"))
            {
                return null;
            }

            var element = (NationalityCountry)xalReader.ReadCountry(new NationalityCountry(), "Country", XmlNS);
            var attrs = _XmlAttribute.GetAttributes(element.ExtendedAttributes);
            attrs = ReadNationalityCountryAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            element.ExtendedAttributes = _XmlAttribute.RemoveMissedAttributes(element.ExtendedAttributes, attrs);
            return element;
        }

        public Nationalities ReadNationalities()
        {
            if (!CheckElement("Nationalities"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Nationalities();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadNationalityCountry();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadNationalityCountry();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public OccupationElement ReadOccupationElement()
        {
            if (!CheckElement("OccupationElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new OccupationElement(value);
            attrs = ReadOccupationElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Occupation ReadOccupation()
        {
            if (!CheckElement("Occupation"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Occupation();
            attrs = ReadOccupationAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                var sub1 = ReadOccupationElement();
                while (sub1 != null)
                {
                    element.Add(sub1);
                    sub1 = ReadOccupationElement();
                }

                element.Employer = xnlReader.ReadOrganisationName("Employer", XmlNS);
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public Occupations ReadOccupations()
        {
            if (!CheckElement("Occupations"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Occupations();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadOccupation();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadOccupation();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public OrganisationInfo ReadOrganisationInfo()
        {
            if (!CheckElement("OrganisationInfo"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new OrganisationInfo();
            attrs = ReadOrganisationInfoAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // from empty element to next node
            return element;
        }

        public PersonInfo ReadPersonInfo()
        {
            if (!CheckElement("PersonInfo"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new PersonInfo();
            attrs = ReadPersonInfoAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // from empty element to next node
            return element;
        }

        public PhysicalInfoFreeTextLine ReadPhysicalInfoFreeTextLine()
        {
            if (!CheckElement("FreeTextLine"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new PhysicalInfoFreeTextLine(value);
            attrs = ReadPhysicalInfoFreeTextLineAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public PhysicalFeature ReadPhysicalFeature()
        {
            if (!CheckElement("Feature"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new PhysicalFeature(value);
            attrs = ReadPhysicalFeatureAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public BodyMark ReadBodyMark()
        {
            if (!CheckElement("BodyMark"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new BodyMark(value);
            attrs = ReadBodyMarkAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Disability ReadDisability()
        {
            if (!CheckElement("Disability"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Disability(value);
            attrs = ReadDisabilityAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Allergy ReadAllergy()
        {
            if (!CheckElement("Allergy"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Allergy(value);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public HealthCondition ReadHealthCondition()
        {
            if (!CheckElement("HealthCondition"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new HealthCondition(value);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public PhysicalInfo ReadPhysicalInfo()
        {
            if (!CheckElement("PhysicalInfo"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new PhysicalInfo();
            attrs = ReadPhysicalInfoAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                var sub1 = ReadPhysicalInfoFreeTextLine();
                while (sub1 != null)
                {
                    if (element.FreeTextLines == null)
                    {
                        element.FreeTextLines = new Collection<PhysicalInfoFreeTextLine>();
                    }

                    element.FreeTextLines.Add(sub1);
                    sub1 = ReadPhysicalInfoFreeTextLine();
                }

                var sub2 = ReadPhysicalFeature();
                while (sub2 != null)
                {
                    if (element.Features == null)
                    {
                        element.Features = new Collection<PhysicalFeature>();
                    }

                    element.Features.Add(sub2);
                    sub2 = ReadPhysicalFeature();
                }

                var sub3 = ReadBodyMark();
                while (sub3 != null)
                {
                    if (element.BodyMarks == null)
                    {
                        element.BodyMarks = new Collection<BodyMark>();
                    }

                    element.BodyMarks.Add(sub3);
                    sub3 = ReadBodyMark();
                }

                var sub4 = ReadDisability();
                while (sub4 != null)
                {
                    if (element.Disabilities == null)
                    {
                        element.Disabilities = new Collection<Disability>();
                    }

                    element.Disabilities.Add(sub4);
                    sub4 = ReadDisability();
                }

                var sub5 = ReadAllergy();
                while (sub5 != null)
                {
                    if (element.Allergies == null)
                    {
                        element.Allergies = new Collection<Allergy>();
                    }

                    element.Allergies.Add(sub5);
                    sub5 = ReadAllergy();
                }

                var sub6 = ReadHealthCondition();
                while (sub6 != null)
                {
                    if (element.HealthConditions == null)
                    {
                        element.HealthConditions = new Collection<HealthCondition>();
                    }

                    element.HealthConditions.Add(sub6);
                    sub6 = ReadHealthCondition();
                }
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public PersonPreference ReadPersonPreference()
        {
            if (!CheckElement("Preference"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new PersonPreference(value);
            attrs = ReadPersonPreferenceAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public PersonPreferences ReadPersonPreferences()
        {
            if (!CheckElement("Preferences"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new PersonPreferences();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadPersonPreference();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadPersonPreference();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public QualificationElement ReadQualificationElement()
        {
            if (!CheckElement("QualificationElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new QualificationElement(value);
            attrs = ReadQualificationElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Qualification ReadQualification()
        {
            if (!CheckElement("Qualification"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Qualification();
            attrs = ReadQualificationAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                var sub1 = ReadQualificationElement();
                while (sub1 != null)
                {
                    element.Add(sub1);
                    sub1 = ReadQualificationElement();
                }

                element.Institution = xnlReader.ReadOrganisationName("Institution", XmlNS);
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public Qualifications ReadQualifications()
        {
            if (!CheckElement("Qualifications"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Qualifications();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadQualification();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadQualification();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public Relationship ReadRelationship()
        {
            if (!CheckElement("Relationship"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Relationship();
            attrs = ReadRelationshipAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                element.NameLine = xnlReader.ReadNameLine();
                element.PersonName = xnlReader.ReadPersonName();
                element.OrganisationName = xnlReader.ReadOrganisationName();
                element.Addresses = ReadAddresses();
                element.ContactNumbers = ReadContactNumbers();
                element.ElectronicAddressIdentifiers = ReadElectronicAddressIdentifiers();
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public Relationships ReadRelationships()
        {
            if (!CheckElement("Relationships"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Relationships();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadRelationship();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadRelationship();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public Revenue ReadRevenue()
        {
            if (!CheckElement("Revenue"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new Revenue(value);
            attrs = ReadRevenueAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Revenues ReadRevenues()
        {
            if (!CheckElement("Revenues"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Revenues();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadRevenue();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadRevenue();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public Stock ReadStock()
        {
            if (!CheckElement("Stock"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Stock();
            attrs = ReadStockAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // from empty element to next node
            return element;
        }

        public Stocks ReadStocks()
        {
            if (!CheckElement("Stocks"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Stocks();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadStock();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadStock();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public VehicleElement ReadVehicleElement()
        {
            if (!CheckElement("VehicleElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new VehicleElement(value);
            attrs = ReadVehicleElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Vehicle ReadVehicle()
        {
            if (!CheckElement("Vehicle"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Vehicle();
            attrs = ReadVehicleAttributes(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                var sub1 = ReadVehicleElement();
                while (sub1 != null)
                {
                    element.Add(sub1);
                    sub1 = ReadVehicleElement();
                }
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public Vehicles ReadVehicles()
        {
            if (!CheckElement("Vehicles"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Vehicles();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadVehicle();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadVehicle();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public VisaElement ReadVisaElement()
        {
            if (!CheckElement("VisaElement"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var value = reader.ReadElementContentAsString();
            var element = new VisaElement(value);
            attrs = ReadVisaElementAttributes(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            return element;
        }

        public Visa ReadVisa()
        {
            if (!CheckElement("Visa"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Visa();
            attrs = ReadVisaAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                var sub1 = ReadVisaElement();
                while (sub1 != null)
                {
                    element.Add(sub1);
                    sub1 = ReadVisaElement();
                }
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public Visas ReadVisas()
        {
            if (!CheckElement("Visas"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new Visas();
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            var sub1 = ReadVisa();
            while (sub1 != null)
            {
                element.Add(sub1);
                sub1 = ReadVisa();
            }

            reader.Read(); // from end element to next node
            return element;
        }

        public OrganisationDetailsType ReadOrganisationDetails()
        {
            if (!CheckElement("OrganisationDetails"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new OrganisationDetailsType();
            attrs = ReadOrganisationDetailsAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = xLinkReader.Read(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            attrs = ctReader.ReadLanguageCodeGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            element.FreeTextLines = ReadFreeTextLines();
            var organisationName = xnlReader.ReadOrganisationName();
            while (organisationName != null)
            {
                if (element.OrganisationNames == null)
                {
                    element.OrganisationNames = new List<OrganisationNameType>();
                }

                element.OrganisationNames.Add(organisationName);
                organisationName = xnlReader.ReadOrganisationName();
            }

            element.Addresses = ReadAddresses();
            element.Accounts = ReadAccounts();
            element.ContactNumbers = ReadContactNumbers();
            element.Documents = ReadDocuments();
            element.ElectronicAddressIdentifiers = ReadElectronicAddressIdentifiers();
            element.Events = ReadEvents();
            element.Identifiers = ReadIdentifiers();
            element.Memberships = ReadMemberships();
            element.Relationships = ReadRelationships();
            element.Revenues = ReadRevenues();
            element.Stocks = ReadStocks();
            element.Vehicles = ReadVehicles();
            element.OrganisationInfo = ReadOrganisationInfo();
            reader.Read(); // from end element to next node
            return element;
        }

        public PartyType ReadParty()
        {
            if (!CheckElement("Party"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new PartyType();
            attrs = ReadPartyAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = xLinkReader.Read(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            attrs = ctReader.ReadLanguageCodeGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            if (!reader.IsEmptyElement)
            {
                reader.Read(); // to first child element
                element.FreeTextLines = ReadFreeTextLines();
                element.PartyName = xnlReader.ReadPartyName("PartyName", XmlNS);
                element.Addresses = ReadAddresses();
                element.Accounts = ReadAccounts();
                element.ContactNumbers = ReadContactNumbers();
                element.Documents = ReadDocuments();
                element.ElectronicAddressIdentifiers = ReadElectronicAddressIdentifiers();
                element.Events = ReadEvents();
                element.Identifiers = ReadIdentifiers();
                element.Memberships = ReadMemberships();
                element.Relationships = ReadRelationships();
                element.Revenues = ReadRevenues();
                element.Stocks = ReadStocks();
                element.Vehicles = ReadVehicles();
                element.OrganisationInfo = ReadOrganisationInfo();
                element.PersonInfo = ReadPersonInfo();
                element.BirthInfo = ReadBirthInfo();
                element.CountriesOfResidence = ReadCountriesOfResidence();
                element.Favourites = ReadFavourites();
                element.Habits = ReadHabits();
                element.Hobbies = ReadHobbies();
                element.Languages = ReadLanguages();
                element.Nationalities = ReadNationalities();
                element.Occupations = ReadOccupations();
                element.PhysicalInfo = ReadPhysicalInfo();
                element.Preferences = ReadPersonPreferences();
                element.Qualifications = ReadQualifications();
                element.Visas = ReadVisas();
            }

            reader.Read(); // from empty or end element to next node
            return element;
        }

        public PersonDetailsType ReadPersonDetails()
        {
            if (!CheckElement("PersonDetails"))
            {
                return null;
            }

            var attrs = _XmlAttribute.GetAttributes(reader);
            var element = new PersonDetailsType();
            attrs = ReadPersonDetailsAttributes(element, attrs);
            attrs = ctReader.ReadValidityDateGroup(element, attrs);
            attrs = ctReader.ReadDataQualityGroup(element, attrs);
            attrs = ctReader.ReadLanguageCodeGroup(element, attrs);
            ctReader.ReadExtendedAttributes(element, attrs);
            reader.Read(); // to first child element
            element.FreeTextLines = ReadFreeTextLines();
            var personName = xnlReader.ReadPersonName();
            while (personName != null)
            {
                if (element.PersonNames == null)
                {
                    element.PersonNames = new List<PersonNameType>();
                }

                element.PersonNames.Add(personName);
                personName = xnlReader.ReadPersonName();
            }

            element.Addresses = ReadAddresses();
            element.Accounts = ReadAccounts();
            element.ContactNumbers = ReadContactNumbers();
            element.Documents = ReadDocuments();
            element.ElectronicAddressIdentifiers = ReadElectronicAddressIdentifiers();
            element.Events = ReadEvents();
            element.Identifiers = ReadIdentifiers();
            element.Memberships = ReadMemberships();
            element.Relationships = ReadRelationships();
            element.Revenues = ReadRevenues();
            element.Stocks = ReadStocks();
            element.Vehicles = ReadVehicles();
            element.PersonInfo = ReadPersonInfo();
            element.BirthInfo = ReadBirthInfo();
            element.CountriesOfResidence = ReadCountriesOfResidence();
            element.Favourites = ReadFavourites();
            element.Habits = ReadHabits();
            element.Hobbies = ReadHobbies();
            element.Languages = ReadLanguages();
            element.Nationalities = ReadNationalities();
            element.Occupations = ReadOccupations();
            element.PhysicalInfo = ReadPhysicalInfo();
            element.Preferences = ReadPersonPreferences();
            element.Qualifications = ReadQualifications();
            element.Visas = ReadVisas();
            reader.Read(); // from end element to next node
            return element;
        }

        public IEnumerable<_XmlAttribute> ReadAccountElementAttributes(
            AccountElement element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new AccountElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadAccountAttributes(
            Account element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new AccountTypeList(xmlAttribute.Value);
                            continue;
                        case "OwnershipType":
                            element.OwnershipType = new AccountOwnershipTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadBirthInfoElementAttributes(
           BirthInfoElement element,
           IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new BirthInfoElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadBirthInfoAttributes(
           BirthInfo element,
           IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "BirthDateTime":
                            element.BirthDateTime = new XSDateTime(xmlAttribute.Value);
                            continue;
                        case "BirthDateTimePrecision":
                            element.BirthDateTimePrecision = new XSDuration(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadContactNumberElementAttributes(
           ContactNumberElement element,
           IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new ContactNumberElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadContactNumberAttributes(
           ContactNumber element,
           IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "CommunicationMediaType":
                            element.CommunicationMediaType = new CommunicationMediaTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "Usage":
                            element.Usage = new ContactNumberUsageList(xmlAttribute.Value);
                            continue;
                        case "ContactHours":
                            element.ContactHours = new CTString(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadCountryOfResidenceAttributes(
           CountryOfResidence element,
           IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new ResidencyTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadDocumentElementAttributes(
          DocumentElement element,
          IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new DocumentElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadDocumentAttributes(
         Document element,
         IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new DocumentTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadElectronicAddressIdentifierAttributes(
        ElectronicAddressIdentifier element,
        IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new ElectronicAddressIdentifierTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "Usage":
                            element.Usage = new ElectronicAddressIdentifierUsageList(xmlAttribute.Value);
                            continue;
                        case "Label":
                            element.Label = new CTString(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadEventAttributes(
            Event element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new EventTypeList(xmlAttribute.Value);
                            continue;
                        case "Date":
                            element.Date = new XSDateTime(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadFavouriteAttributes(
            Favourite element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new PersonFavouriteTypeList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadFreeTextLineAttributes(
            FreeTextLine element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new FreeTextLineTypeList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadHabitAttributes(
            Habit element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new HabitTypeList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadHobbyAttributes(
            Hobby element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new HobbyTypeList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadIdentifierElementAttributes(
            IdentifierElement element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new PartyIdentifierElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadIdentifierAttributes(
            Identifier element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new PartyIdentifierTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadLanguageAttributes(
            Language element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new LanguageTypeList(xmlAttribute.Value);
                            continue;
                        case "Speak":
                            element.Speak = new LanguageSkillsList(xmlAttribute.Value);
                            continue;
                        case "Read":
                            element.Read = new LanguageSkillsList(xmlAttribute.Value);
                            continue;
                        case "Write":
                            element.Write = new LanguageSkillsList(xmlAttribute.Value);
                            continue;
                        case "Understand":
                            element.Understand = new LanguageSkillsList(xmlAttribute.Value);
                            continue;
                        case "Preference":
                            element.Preference = new LanguagePreferenceList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadMembershipElementAttributes(
            MembershipElement element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new MembershipElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadMembershipAttributes(
            Membership element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new MembershipTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadNationalityCountryAttributes(
            NationalityCountry element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new NationalityTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadOccupationElementAttributes(
            OccupationElement element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new OccupationElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadOccupationAttributes(
            Occupation element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "isSelfEmployed":
                            element.IsSelfEmployed = new XSBoolean(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadOrganisationInfoAttributes(
            OrganisationInfo element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new OrganisationInfoTypeList(xmlAttribute.Value);
                            continue;
                        case "CategoryType":
                            element.CategoryType = new OrganisationCategoryTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "Nature":
                            element.Nature = new OrganisationInfoNatureList(xmlAttribute.Value);
                            continue;
                        case "IndustryType":
                            element.IndustryType = new IndustryTypeList(xmlAttribute.Value);
                            continue;
                        case "IndustryCode":
                            element.IndustryCode = new IndustryCodeList(xmlAttribute.Value);
                            continue;
                        case "IndustryCodeType":
                            element.IndustryCodeType = new CTString(xmlAttribute.Value);
                            continue;
                        case "NumberOfEmployees":
                            element.NumberOfEmployees = new CTString(xmlAttribute.Value);
                            continue;
                        case "OperatingHourStartTime":
                            element.OperatingHourStartTime = new XSTime(xmlAttribute.Value);
                            continue;
                        case "OperatingHourEndTime":
                            element.OperatingHourEndTime = new XSTime(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadPersonInfoAttributes(
            PersonInfo element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Age":
                            element.Age = new CTString(xmlAttribute.Value);
                            continue;
                        case "CategoryType":
                            element.CategoryType = new PersonCategoryTypeList(xmlAttribute.Value);
                            continue;
                        case "PhysicalStatus":
                            element.PhysicalStatus = new PhysicalStatusList(xmlAttribute.Value);
                            continue;
                        case "MaritalStatus":
                            element.MaritalStatus = new MaritalStatusList(xmlAttribute.Value);
                            continue;
                        case "Ethnicity":
                            element.Ethnicity = new PersonEthnicityList(xmlAttribute.Value);
                            continue;
                        case "Gender":
                            element.Gender = new GenderList(xmlAttribute.Value);
                            continue;
                        case "Religion":
                            element.Religion = new ReligionList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadPhysicalInfoFreeTextLineAttributes(
            PhysicalInfoFreeTextLine element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new PhysicalInfoFreeTextTypeList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadPhysicalFeatureAttributes(
            PhysicalFeature element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new FeatureTypeList(xmlAttribute.Value);
                            continue;
                        case "UnitType":
                            element.UnitType = new UnitTypeList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadBodyMarkAttributes(
            BodyMark element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Part":
                            element.Part = new BodyMarkPartList(xmlAttribute.Value);
                            continue;
                        case "Location":
                            element.Location = new BodyMarkPartLocationList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadDisabilityAttributes(
            Disability element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Cause":
                            element.Cause = new DisabilityCauseList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadPhysicalInfoAttributes(
            PhysicalInfo element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "BloodGroup":
                            element.BloodGroup = new BloodGroupList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadPersonPreferenceAttributes(
            PersonPreference element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new PreferenceTypeList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadQualificationElementAttributes(
            QualificationElement element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new QualificationElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadQualificationAttributes(
            Qualification element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadRelationshipAttributes(
            Relationship element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "PartyType":
                            element.PartyType = new PartyTypeList(xmlAttribute.Value);
                            continue;
                        case "RelationshipWithPerson":
                            element.RelationshipWithPerson = new PersonRelationshipTypeList(xmlAttribute.Value);
                            continue;
                        case "RelationshipWithOrganisation":
                            element.RelationshipWithOrganisation = 
                                new OrganisationRelationshipTypeList(xmlAttribute.Value);
                            continue;
                        case "RelationshipValidFrom":
                            element.RelationshipValidFrom = new XSDateTime(xmlAttribute.Value);
                            continue;
                        case "RelationshipValidTo":
                            element.RelationshipValidTo = new XSDateTime(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadRevenueAttributes(
            Revenue element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "CurrencyCode":
                            element.CurrencyCode = new RevenueCurrencyCodeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "PeriodFrom":
                            element.PeriodFrom = new XSDateTime(xmlAttribute.Value);
                            continue;
                        case "PeriodTo":
                            element.PeriodTo = new XSDateTime(xmlAttribute.Value);
                            continue;
                        case "Type":
                            element.Type = new RevenueTypeList(xmlAttribute.Value);
                            continue;
                        case "Precision":
                            element.Precision = new XSDecimal(xmlAttribute.Value);
                            continue;
                        case "Source":
                            element.Source = new RevenueSourceList(xmlAttribute.Value);
                            continue;
                        case "CountryName":
                            element.CountryName = new CTString(xmlAttribute.Value);
                            continue;
                        case "AfterTax":
                            element.AfterTax = new XSBoolean(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadStockAttributes(
            Stock element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "ListedCode":
                            element.ListedCode = new CTString(xmlAttribute.Value);
                            continue;
                        case "MarketName":
                            element.MarketName = new CTString(xmlAttribute.Value);
                            continue;
                        case "CountryName":
                            element.CountryName = new CTString(xmlAttribute.Value);
                            continue;
                        case "InvestedDate":
                            element.InvestedDate = new XSDateTime(xmlAttribute.Value);
                            continue;
                        case "ShareQuantity":
                            element.ShareQuantity = new CTString(xmlAttribute.Value);
                            continue;
                        case "ListedDate":
                            element.ListedDate = new XSDateTime(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadVehicleElementAttributes(
            VehicleElement element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new VehicleInfoElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadVehicleAttributes(
            Vehicle element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new VehicleTypeList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadVisaElementAttributes(
            VisaElement element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Type":
                            element.Type = new VisaElementList(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadVisaAttributes(
            Visa element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "EntryByDate":
                            element.EntryByDate = new XSDateTime(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadOrganisationDetailsAttributes(
            OrganisationDetailsType element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Usage":
                            element.Usage = new OrganisationDetailsUsageList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "OrganisationDetailsKey":
                            element.OrganisationDetailsKey = new CTString(xmlAttribute.Value);
                            continue;
                        case "OrganisationDetailsKeyRef":
                            element.OrganisationDetailsKeyRef = new CTString(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadPartyAttributes(
            PartyType element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "PartyType":
                            element.Type = new PartyTypeList(xmlAttribute.Value);
                            continue;
                        case "PartyID":
                            element.PartyId = new CTString(xmlAttribute.Value);
                            continue;
                        case "PartyIDType":
                            element.PartyIdType = new PartyIdTypeList(xmlAttribute.Value);
                            continue;
                        case "ID":
                            element.Id = new CTString(xmlAttribute.Value);
                            continue;
                        case "Usage":
                            element.Usage = new PartyUsageList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "PartyKey":
                            element.PartyKey = new CTString(xmlAttribute.Value);
                            continue;
                        case "PartyKeyRef":
                            element.PartyKeyRef = new CTString(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public IEnumerable<_XmlAttribute> ReadPersonDetailsAttributes(
            PersonDetailsType element,
            IEnumerable<_XmlAttribute> attributes)
        {
            foreach (var xmlAttribute in attributes)
            {
                if (xmlAttribute.NS == XmlNS)
                {
                    switch (xmlAttribute.Name)
                    {
                        case "Usage":
                            element.Usage = new PersonDetailsUsageList(xmlAttribute.Value);
                            continue;
                        case "Status":
                            element.Status = new StatusList(xmlAttribute.Value);
                            continue;
                        case "PersonDetailsKey":
                            element.PersonDetailsKey = new CTString(xmlAttribute.Value);
                            continue;
                        case "PersonDetailsKeyRef":
                            element.PersonDetailsKeyRef = new CTString(xmlAttribute.Value);
                            continue;
                    }
                }

                yield return xmlAttribute;
            }
        }

        public bool CheckElement(string name)
        {
            var ns = reader.NamespaceURI;
            var elem = reader.NodeType == XmlNodeType.Element ? reader.LocalName : null;
            return elem != null && ns == XmlNS && elem == name;
        }
    }
}